#include <iostream>
#include <string>
using namespace std;

#define TWO

#if defined ONE

struct Books
{
    string title;
    string author;
    string subject;
    int    book_id;
    // 这里是构造函数 ,用于初始化这些成员
    Books(string t, string a, string s, int id) : title(t), author(a), subject(s), book_id(id) {}
};

// 形参 是一个 常量指针(就是 指向的内容不可以改变)
void PrintBookInfo(const Books* BookPtr)
{
    cout << "书籍标题" << BookPtr->title << endl;
    cout << "书籍作者" << BookPtr->author << endl;
    cout << "书籍类目" << BookPtr->subject << endl;
    cout << "书籍ID" << BookPtr->book_id << endl;
}

int main(void)
{
    struct Books Book1("C++ 教程", "Runoob", "编程语言", 12345);   // 相当于是在创建对象的同时，对对象进行初始化(其实是调用构造函数)
    struct Books Book2("CSS 教程", "Runoob", "前端技术", 12346);

    struct Books* Book1Ptr = &Book1;
    struct Books* Book2Ptr = &Book2;

    PrintBookInfo(Book1Ptr);
    PrintBookInfo(Book2Ptr);

    return 0;
}

#elif defined TWO

typedef struct Books
{
    string title;
    string author;
    string subject;
    int    book_id;

    // 构造函数
    Books(string t, string a, string s, int id) : title(t), author(a), subject(s), book_id(id) {}

    //结构体里面的成员函数
    void PrintInfo() const   // 函数添加const关键字是为了啥  原来是为了保证该函数不会修改类的成员变量(mutable修饰的变量除外)
    {
        cout << "书籍标题: " << title << endl;
        cout << "书籍作者: " << author << endl;
        cout << "书籍类目: " << subject << endl;
        cout << "书籍ID: " << book_id << endl;
    }
} Book_Typedef;

void PrintBookByRef(const Book_Typedef& Book)
{
    // 上面添加 const 是为了防止在函数里面修改 实参
    Book.PrintInfo();
}

int main(void)
{
    Book_Typedef Book1("C++ 教程", "Runoob", "编程语言", 12345);

    PrintBookByRef(Book1);

    return 0;
}

#endif

/**
 *  C++里面结构体支持构造函数，成员函数和访问权限控制,可以实现面向对象的设计
 *  结构体里面的成员变量，默认是public的访问权限
 *
 *  结构体与class类似,你可以在struct中使用public,private和protected来定义成员的访问权限，默认所有成员都是public,而class里面默认是private
 *
 *  typedef long int * pint32;
 *
 *  那么 pint32 i; 和下面的等同
 *       long int * i;
 *
 *  可以将struct当作一种简化形式的class,适合用于没有太多复杂功能的简单数据封装
 *
 */